package avicit.bdp.dms.das.rest;

import avicit.bdp.common.database.ColumnMeta;
import avicit.bdp.common.database.TableMeta;
import avicit.bdp.common.datasource.BaseDataSource;
import avicit.bdp.common.service.dto.CommonTypeDTO;
import avicit.bdp.common.service.dto.DataSourceDTO;
import avicit.bdp.common.service.service.DataQueryService;
import avicit.bdp.common.service.service.DataSourceService;
import avicit.bdp.common.utils.database.DBUtils;
import avicit.bdp.common.utils.database.adapter.DbAdapter;
import avicit.bdp.common.utils.database.adapter.DbAdapterUtils;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.*;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

/** 数据源管理REST接口 */
@RestController
@Api(tags = "数据源管理REST接口")
@RequestMapping("/api/bdp/dms/das/dataSource")
public class BdpDasDatasourceRest {
  @Autowired private DataSourceService dataSourceService;

  @Autowired private DataQueryService dataQueryService;

  /** 新增数据源對象 */
  @ApiOperation(value = "新增对象")
  @PostMapping("/insertDataSource")
  public ResponseMsg<String> insertDataSource(@RequestBody DataSourceDTO bdpDasDatasource) {
    ResponseMsg<String> responseMsg = new ResponseMsg<>();
    bdpDasDatasource.setOrgIdentity(ThreadContextHelper.getOrgId());
    responseMsg.setResponseBody(dataSourceService.insertBdpDasDatasource(bdpDasDatasource));
    return responseMsg;
  }

  /** 批量新增数据源 注意： 1、数据开发工作台-资源管理-数据源管理，获取公共数据源列表 2、数据计算-离线计算/实时计算/机器学习等-数据源管理，获取公共数据源列表 */
  @ApiOperation(value = "新增对象")
  @PostMapping("/batchInsertDataSource")
  public ResponseMsg<Boolean> batchInsertDataSource(
      @RequestBody List<DataSourceDTO> bdpDasDatasourceList) {
    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(dataSourceService.batchInsertDataSource(bdpDasDatasourceList));

    return responseMsg;
  }

  /** 修改数据源对象 */
  @ApiOperation(value = "修改对象")
  @PostMapping("/updateDataSource")
  public ResponseMsg<String> updateDataSource(@RequestBody DataSourceDTO bdpDasDatasource) {
    ResponseMsg<String> responseMsg = new ResponseMsg<>();
    dataSourceService.updateBdpDasDatasource(bdpDasDatasource);
    return responseMsg;
  }

  /** 删除数据源对象 */
  @ApiOperation(value = "按主键单条删除")
  @ApiImplicitParams({
    @ApiImplicitParam(
        name = "id",
        value = "id",
        dataType = "String",
        paramType = "body",
        required = true)
  })
  @PostMapping("/deleteDataSource")
  public ResponseMsg<Integer> deleteById(@ApiIgnore @RequestBody Map<String, String> queryMap) {
    ResponseMsg<Integer> responseMsg = new ResponseMsg<>();
    dataSourceService.deleteBdpDasDatasourceById(queryMap.get("id"));
    return responseMsg;
  }

  /** 根据条件获取公共数据源列表（管理界面不做权限控制） 注意： 1、资源管理-数据源管理，获取公共数据源列表 */
  @ApiOperation(value = "按条件分页查询")
  @ApiImplicitParams({
    @ApiImplicitParam(value = "末级节点分类Id", name = "typeId", dataType = "String"),
    @ApiImplicitParam(value = "查询关键字", name = "keyWords", dataType = "String"),
    @ApiImplicitParam(value = "当前页", name = "pageNo", dataType = "Integer"),
    @ApiImplicitParam(value = "每页大小", name = "pageSize", dataType = "Integer")
  })
  @GetMapping("/searchDataSource")
  public ResponseMsg<QueryRespBean<DataSourceDTO>> searchDataSource(
      @RequestParam String typeId,
      @RequestParam(required = false) String keyWords,
      @RequestParam(defaultValue = "1", required = false) Integer pageNo,
      @RequestParam(defaultValue = "10", required = false) Integer pageSize) {

    ResponseMsg<QueryRespBean<DataSourceDTO>> responseMsg = new ResponseMsg<>();
    QueryRespBean<DataSourceDTO> result =
        dataSourceService.searchDataSource(typeId, keyWords, pageNo, pageSize);
    responseMsg.setResponseBody(result);
    return responseMsg;
  }

  /**
   * 根据项目id获取数据源 注意： 1、数据开发工作台-资源管理-数据源管理/各种关联算子，获取项目数据源 2、据计算-离线计算/实时计算/机器学习等-数据源管理/各种关联算子，获取项目数据源
   */
  @ApiOperation(value = "按项目ID分页查询")
  @ApiImplicitParams({
          @ApiImplicitParam(value = "项目ID", name = "projectId", dataType = "String"),
          @ApiImplicitParam(value = "查询关键字", name = "keyWords", dataType = "String"),
          @ApiImplicitParam(value = "当前页", name = "pageNo", dataType = "Integer"),
          @ApiImplicitParam(value = "每页大小", name = "pageSize", dataType = "Integer"),
          @ApiImplicitParam(value = "密级", name = "secretLevel", dataType = "String")
  })
  @GetMapping("/getListForDataSource")
  public ResponseMsg<QueryRespBean<DataSourceDTO>> getListForDataSource(
      @RequestParam String projectId,
      @RequestParam(required = false) String keyWords,
      @RequestParam(defaultValue = "1", required = false) Integer pageNo,
      @RequestParam(defaultValue = "10", required = false) Integer pageSize,
      @RequestParam(required = false) String secretLevel) {

    ResponseMsg<QueryRespBean<DataSourceDTO>> responseMsg = new ResponseMsg<>();
    QueryRespBean<DataSourceDTO> result = dataSourceService.getListForDataSource(projectId, keyWords, pageNo, pageSize, secretLevel);
    responseMsg.setResponseBody(result);
    return responseMsg;
  }

  /** 获取项目数据源（不分页） 注意： 1、数据开发工作台中表管理、算子管理等获取项目数据源 2、数据计算中表管理、算子管理等获取项目数据源 */
  @ApiOperation(value = "按项目ID不分页查询")
  @ApiImplicitParams({
    @ApiImplicitParam(value = "项目ID", name = "projectId", dataType = "String"),
    @ApiImplicitParam(value = "数据源类型", name = "dataSourceType", dataType = "String"),
    @ApiImplicitParam(value = "查询关键字", name = "keyWords", dataType = "String")
  })
  @GetMapping("/getProjectDataSourceList")
  public ResponseMsg<List<DataSourceDTO>> getProjectDataSourceList(
      @RequestParam String projectId,
      @RequestParam(required = false) String dataSourceType,
      @RequestParam(required = false) String keyWords) {
    ResponseMsg<List<DataSourceDTO>> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(
        dataSourceService.getProjectDataSourceList(projectId, dataSourceType, keyWords));

    return responseMsg;
  }

  /** 数据空间中判断数据源项目是否重复 */
  @ApiOperation(value = "判断数据源名称是否重复")
  @ApiImplicitParams({
    @ApiImplicitParam(
        name = "id",
        value = "id",
        dataType = "String",
        paramType = "body",
        required = true),
    @ApiImplicitParam(
        name = "projectId",
        value = "数据空间id",
        dataType = "String",
        paramType = "body",
        required = true),
    @ApiImplicitParam(
        name = "name",
        value = "数据源名称",
        dataType = "String",
        paramType = "body",
        required = true)
  })
  @PostMapping("/isSameProName")
  public ResponseMsg<Boolean> isSameProName(@ApiIgnore @RequestBody Map<String, String> queryMap) {
    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    String id = MapUtils.getString(queryMap, "id", "");
    String projectId = MapUtils.getString(queryMap, "projectId", "");
    String name = MapUtils.getString(queryMap, "name", "");
    Boolean flag = dataSourceService.isSameProName(id, projectId, name);
    responseMsg.setResponseBody(flag);
    return responseMsg;
  }

  /** 数据源测试连接 */
  @ApiOperation(value = "数据源测试连接")
  @PostMapping("/testDSObj")
  public ResponseMsg<Map<String, Object>> testDbObj(@RequestBody DataSourceDTO bdpDasDatasource) {
    ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
    BaseDataSource baseDataSource = DBUtils.getBaseDataSource(bdpDasDatasource);
    Map<String, Object> map = dataSourceService.testDbConnect(baseDataSource);
    responseMsg.setResponseBody(map);
    return responseMsg;
  }

  /** 查询数据源列表 */
  @ApiOperation(value = "查询数据源列表")
  @PostMapping("/queryDSList")
  public ResponseMsg<Integer> queryDataSourceList(@RequestBody DataSourceDTO bdpDasDatasource) {
    ResponseMsg<Integer> responseMsg = new ResponseMsg<>();
    BaseDataSource baseDataSource = DBUtils.getBaseDataSource(bdpDasDatasource);
    dataSourceService.testDbConnect(baseDataSource);
    return responseMsg;
  }

  /** 判断数据源名称是否重复 */
  @ApiOperation(value = "判断数据源名称是否重复")
  @ApiImplicitParams({
    @ApiImplicitParam(value = "数据源id", name = "id", dataType = "String"),
    @ApiImplicitParam(value = "数据源名称", name = "name", dataType = "String"),
    @ApiImplicitParam(value = "数据空间id", name = "projectId", dataType = "String")
  })
  @GetMapping("/isSameName")
  public ResponseMsg<Integer> isSameName(
      @RequestParam(required = false) String datasourceId,
      @RequestParam String name,
      @RequestParam(required = false) String projectId) {

    ResponseMsg<Integer> responseMsg = new ResponseMsg<>();
    Integer flag = dataSourceService.isSameName(datasourceId, name, projectId);
    responseMsg.setResponseBody(flag);
    return responseMsg;
  }

  /** 根据类型获取数据源 注意： 1、DDS模型设计时，根据数据源分类获取列表 2、数据开发工作台-资源管理-表管理，导入时根据type获取项目数据源 */
  @ApiOperation(value = "根据类型获取数据源")
  @ApiImplicitParams({
          @ApiImplicitParam(value = "数据源类型", name = "dataSourceType", dataType = "String"),
          @ApiImplicitParam(value = "数据空间id", name = "projectId", dataType = "String"),
          @ApiImplicitParam(value = "密级", name = "secretLevel", dataType = "String")
  })
  @GetMapping("/getDataSourceListByType")
  public ResponseMsg<List<DataSourceDTO>> getDataSourceListByType(
      @RequestParam(required = false) String dataSourceType,
      @RequestParam(required = false) String projectId,
      @RequestParam(required = false) String secretLevel) {
    ResponseMsg<List<DataSourceDTO>> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(
        dataSourceService.getDataSourceListByType(dataSourceType, projectId, secretLevel));

    return responseMsg;
  }

  /** 根据分类id获取数据源（根据角色进行权限过滤） 注意： 1、数据模型管理-模型落库，获取数据源列表； 2、数据模型管理-创建模型时，选择数据源列表； */
  @ApiOperation(value = "根据分类ID获取数据源")
  @ApiImplicitParam(value = "分类id", name = "typeId", dataType = "String", required = true)
  @GetMapping("/getDataSourceListByTypeId")
  public ResponseMsg<List<DataSourceDTO>> getDataSourceListByTypeId(@RequestParam String typeId) {
    ResponseMsg<List<DataSourceDTO>> responseMsg = new ResponseMsg<>();

    List<DataSourceDTO> result = dataSourceService.getDataSourceListByTypeId(typeId);
    responseMsg.setResponseBody(result);

    return responseMsg;
  }

  /** 测试 */
  @GetMapping("/test")
  @ApiOperation(value = "测试")
  public ResponseMsg<Long> test(@RequestParam String id) throws Exception {
    ResponseMsg<Long> responseMsg = new ResponseMsg<>();
    DataSourceDTO dataSourceDTO = dataSourceService.selectByPrimaryKey(id);

    DbAdapter dbAdapter = DbAdapterUtils.getDbAdapter(dataSourceDTO.getDatasourceType());
    BaseDataSource baseDataSource = DBUtils.getBaseDataSource(dataSourceDTO);

    Long version = dbAdapter.getOtherCount(dataSourceDTO);
    responseMsg.setResponseBody(version);
    return responseMsg;
  }

  /** 获取所有数据源 注意： 1、授权界面，根据角色ID和分类ID获取数据源信息（数据源对象中包含权限） */
  @ApiOperation(value = "按条件分页查询")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "roleId", value = "角色Id", dataType = "String", required = true),
    @ApiImplicitParam(name = "typeId", value = "末级节点分类Id", dataType = "String", required = true),
    @ApiImplicitParam(name = "keyWords", value = "查询关键字", dataType = "String"),
    @ApiImplicitParam(name = "pageNo", value = "当前页", dataType = "Integer"),
    @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "Integer")
  })
  @GetMapping("/getAllDataSource")
  @Deprecated
  public ResponseMsg<QueryRespBean<DataSourceDTO>> getAllDataSource(
      @RequestParam String roleId,
      @RequestParam String typeId,
      @RequestParam(required = false) String keyWords,
      @RequestParam(defaultValue = "1", required = false) Integer pageNo,
      @RequestParam(defaultValue = "10", required = false) Integer pageSize) {
    ResponseMsg<QueryRespBean<DataSourceDTO>> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        dataSourceService.getAllDataSource(roleId, typeId, keyWords, pageNo, pageSize));
    return responseMsg;
  }

  /**
   * 查询公共数据源(树结构) 注意： 1、授权角色，获取整棵树（包括分类节点和数据源）
   *
   * @param type
   * @return
   */
  @ApiOperation(value = "查询公共数据源(树结构)")
  @ApiImplicitParam(value = "分类类型", name = "type", dataType = "String")
  @GetMapping("/getDataSourceTree")
  public ResponseMsg<List<CommonTypeDTO>> getDataSourceTree(@RequestParam String type) {
    ResponseMsg<List<CommonTypeDTO>> responseMsg = new ResponseMsg<>();
    List<CommonTypeDTO> result = dataSourceService.getDataSourceTree(type);
    responseMsg.setResponseBody(result);
    return responseMsg;
  }

  /**
   * 根据数据源ID查询dbName 注意：提供给DataQuality使用
   *
   * @param datasourceId 数据源ID
   * @return
   */
  @GetMapping("/dbName")
  @ApiOperation(value = "根据数据源ID查询dbName")
  public ResponseMsg<List<String>> getDbName(
      @ApiParam(value = "数据源ID", name = "datasourceId") @RequestParam String datasourceId) {
    ResponseMsg<List<String>> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(this.dataSourceService.getDbName(datasourceId));

    return responseMsg;
  }

  /**
   * 根据数据源ID查询表 注意：提供给DataQuality使用
   *
   * @param datasourceId 数据源ID
   * @return
   */
  @GetMapping("/tableList")
  @ApiOperation(value = "根据数据源ID查询表")
  public ResponseMsg<List<TableMeta>> getTableList(
      @ApiParam(value = "数据源ID", name = "datasourceId") @RequestParam String datasourceId) {
    ResponseMsg<List<TableMeta>> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(this.dataSourceService.getTableList(datasourceId));

    return responseMsg;
  }

  /**
   * 根据数据源ID和表名称查询字段信息 注意：提供给DataQuality使用
   *
   * @param datasourceId 数据源ID
   * @param tableName 表名称
   */
  @GetMapping("/columnList")
  @ApiOperation(value = "根据数据源ID和表名称查询字段信息")
  public ResponseMsg<List<ColumnMeta>> getColumnList(
      @ApiParam(value = "数据源ID", name = "datasourceId") @RequestParam String datasourceId,
      @ApiParam(value = "表名称", name = "tableName") @RequestParam String tableName) {
    ResponseMsg<List<ColumnMeta>> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(this.dataSourceService.getColumnList(datasourceId, tableName));

    return responseMsg;
  }

  /**
   * 根据数据源ID和SQL,预执行
   *
   * @param datasourceId 数据源ID
   * @param sql sql
   */
  @GetMapping("/execute/sql")
  @ApiOperation(value = "预执行SQL")
  public ResponseMsg<Map<String, Object>> executeSql(
      @ApiParam(value = "数据源ID", name = "datasourceId") @RequestParam String datasourceId,
      @ApiParam(value = "sql", name = "sql") @RequestParam String sql) {
    ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
    Map<String, Object> result =
        dataQueryService.getDataListByTable(null, datasourceId, sql, null, 1, 10);
    responseMsg.setResponseBody(result);
    return responseMsg;
  }
}
